iT邦幫忙

2021 iThome 鐵人賽

DAY 11
1

在實際開發中,一定會需要將資料持久化,常見的持久化技術有Spring 自帶的JdbcTemplate、Spring Boot 提供的JPA 規範以及MyBatis,這個系列文會逐一介紹上述三種持久化技術,本篇文章先講最簡單的JdbcTemplate

JDBC 與JdbcTemplate

JDBC,全名為Java Database Connectivity,是一種用於執行SQL 語法的Java API,它將資料庫存取SQL 語法與Java API 分開,讓開發人員開發資料庫應用程式更有彈性。

JdbcTemplate 則是對JDBC 的封裝,目的是為了解決JDBC 每次使用都必須重新進行資料庫連接、處理SQL 語法、傳值、關閉資料庫連接等一系列操作所引發的一系列問題,替開發人員完成了所有JDBC 的底層工作,因此使用JdbcTemplate 就不用每次都進行連結、開啟、關閉等操作。

常用方法

  • batchUpdate : 批量更新。
  • execute : 執行SQL 語法。
  • update : 執行一條插入、更新或刪除語法。
  • query : 查詢並返回相應值。
  • queryForList : 查詢並返回一個List。
  • queryForObject : 查詢並返回一個Object。
  • queryForMap : 查詢並返回一個Map。
  • queryForRowSet : 查詢並返回一個RowSet。

實作

接下來會實作使用JdbcTemplate 對資料庫進行新增查詢修改等操作,由於修改跟刪除都是使用update 方法,這邊就不實作了,完整的程式碼就放在最下方的Github 連結。

新增依賴

<!-- MySQL Driver -->
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
	<scope>runtime</scope>
</dependency>

<!-- JDBC API -->
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

配置資料庫連線

// 設定資料庫位址
spring.datasource.url=jdbc:mysql://localhost:3306/test_project?useUnicode=true&characeterEncoding=utf-8&serverTimezone=Asia/Shanghai

// 設定使用者資訊
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

建立資料表

CREATE TABLE IF NOT EXISTS member_account (
	ID INT PRIMARY KEY AUTO_INCREMENT COMMENT "會員流水號",
	USERNAME VARCHAR(60) UNIQUE NOT NULL COMMENT "帳號",
	PASSWORD VARCHAR(60) NOT NULL COMMENT "密碼",
	SALT VARCHAR(32) NOT NULL COMMENT "鹽值",
	CREATE_BY VARCHAR(60) NOT NULL COMMENT "建立者",
	CREATE_TIME DATETIME NOT NULL COMMENT "建立時間",
	UPDATE_BY VARCHAR(60) NOT NULL COMMENT "修改者",
	UPDATE_TIME DATETIME NOT NULL COMMENT "修改時間"
)DEFAULT CHARSET=utf8mb4

建立實體類

package com.example.demo.entity;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class MemberAccount extends Base {

	private String id;
	private String username;
	private String password;
	private String salt;

}

建立持久層接口

package com.example.demo.dao;

import com.example.demo.entity.MemberAccount;

public interface MemberAccountDao {

	public Integer insert(MemberAccount memberAccount);
	public MemberAccount findMemberAccountByUsername(String username);
	public Integer update(MemberAccount memberAccount);

}

建立持久層實作方法

package com.example.demo.dao.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;

import com.example.demo.dao.MemberAccountDao;
import com.example.demo.entity.MemberAccount;

@Repository
public class MemberAccountDaoImpl implements MemberAccountDao {

	@Autowired
	private JdbcTemplate jdbcTemplate;

	@Autowired
	private NamedParameterJdbcTemplate jdbcNameTemplate;

	@Override
	public Integer insert(MemberAccount memberAccount) {
		// TODO Auto-generated method stub
		String sql = " INSERT INTO test_project.member_account ( "
				  	   + "		USERNAME, PASSWORD, SALT, "
				  	   + "		CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME "
				  	   + " ) "
				  	   + " VALUE ( "
				  	   + "		:username, :password, :salt, "
				  	   + "		:create_by, NOW(), :update_by, NOW() "
				  	   + " ) ";

		SqlParameterSource paramSource = new BeanPropertySqlParameterSource(memberAccount);
		KeyHolder keyHolder = new GeneratedKeyHolder();

		jdbcNameTemplate.update(sql, paramSource, keyHolder);
		return keyHolder.getKey().intValue();
	}

	@Override
	public MemberAccount findMemberAccountByUsername(String username) {
		// TODO Auto-generated method stub
		String sql = " SELECT "
						   + "		ID, USERNAME, PASSWORD, SALT "
						   + " FROM "
						   + "		test_project.member_account "
						   + " WHERE "
						   + "		USERNAME = ? ";

		List<MemberAccount> result = jdbcTemplate.query(sql, new BeanPropertyRowMapper<MemberAccount>(MemberAccount.class), new Object[] { username });
		if(result != null && result.size() > 0) {
			return result.get(0);
		}
		return null;
	}

	@Override
	public Integer update(MemberAccount memberAccount) {
		// TODO Auto-generated method stub
		String sql = " UPDATE "
						   + "		test_project.member_account "
						   + " SET "
						   + "		PASSWORD = :password, UPDATE_BY = :update_by, UPDATE_TIME = NOW() "
						   + " WHERE "
						   + "		ID = :id ";

		SqlParameterSource paramSource = new BeanPropertySqlParameterSource(memberAccount);
		return jdbcNameTemplate.update(sql, paramSource);
	}

}

單元測試方法

package com.example.demo.dao;

import java.util.UUID;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import com.example.demo.entity.MemberAccount;

@SpringBootTest
public class MemberAccountDaoTest {

	@Autowired
	private MemberAccountDao memberAccountDao;

	@Test
	public void insert() {
		MemberAccount memberAccount = new MemberAccount();
		memberAccount.setUsername("username@email.com");
		memberAccount.setPassword("password");

		String salt = UUID.randomUUID().toString().toUpperCase().replaceAll("-", "");
		memberAccount.setSalt(salt);
		memberAccount.setCreate_by(memberAccount.getUsername());
		memberAccount.setUpdate_by(memberAccount.getUsername());

		Integer id = memberAccountDao.insert(memberAccount);
		System.out.println(id);
	}

	@Test
	public void findMemberAccountByUsername() {
		String username = "username@email.com";
		MemberAccount memberAccount = memberAccountDao.findMemberAccountByUsername(username);
		if(memberAccount != null) System.out.println(memberAccount.toString());
	}

	@Test
	public void update() {
		MemberAccount memberAccount = new MemberAccount();
		memberAccount.setId("1");
		memberAccount.setPassword("123456");
		memberAccount.setUpdate_by("username@email.com");

		Integer result = memberAccountDao.update(memberAccount);
		System.out.println(result);
	}

}

Github

使用JDBC 建立持久層及其測試方法

參考網站

(13) 甚麼是 JDBC、ORM、 JPA、ORM框架、Hibernate
JdbcTemplate (Spring Framework 5.3.10 API)


上一篇
Day 10 - Spring Boot 建立專案
下一篇
Day 12 - Spring Boot & MyBatis
系列文
誤打誤撞學了Spring Boot 還當了後端工程師30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言